package utils {

	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.utils.Dictionary;

	/**
	 * Simple way to add inline icons for a Text Field.
	 * @author Pavel
	 * @link www.sprklab.com
	 */
	public class ChangeTextToObject {
		public var txtField:TextField;
		public var icons:Array = new Array();
		public var sprite:MovieClip;
		public var placeHolder:String = "{xxx}";
		private var myString:String;
		private var placeHolderWhite:String;
		private var tempObject:Object;
		private var ico:DisplayObject;
		private var _iconLocs:Array = new Array;
		private var _partialLocs:Array = new Array;
		private var _byLine:Boolean;
		
		
		public function ChangeTextToObject(txt:TextField, lineOption:Boolean=false) {
			
			sprite = new MovieClip();
			txtField = txt;
			byLine=lineOption;
			
			if (txtField.stage != null)
			{
				captureTextField();
			}
			else
			{
				txtField.addEventListener(Event.ADDED_TO_STAGE, captureTextField);
			}
		}
		
		public function captureTextField(e:Event = null):void {
			txtField.parent.addChild(sprite);
			sprite.x = txtField.x;
			sprite.y = txtField.y;
		}
		
		public function getSprite():MovieClip {
			return sprite;
		}
		
		/*
		* Add Icon tag along with a constructor function that will return the display object to put whenever that icon tag is shown 
		*/
		public function addIcon(tag:String, dObject:DisplayObject):void {
			var newIcon:Object = new Object;
			newIcon.tag=tag;
			newIcon.mc=new DuplicateDisplayObject().duplicateImageAsSprite(dObject);
			icons.push(newIcon);
		}
		
		public function reset():void {
			if (_byLine) {
				_partialLocs = [];
				_iconLocs = [];
			}
			while (sprite.numChildren > 0) {
				sprite.removeChildAt(0);
			}
		}
		
		public function forceCleanObjects():void {
			while (sprite.numChildren > 0) {
				sprite.removeChildAt(0);
			}
		}
		
		public function setText(str:String):void {
			myString = str;
			// Remove all existing Smiley Face
			reset();
			
			placeHolderWhite = new String();
			
			for (var i:int = 0; i < placeHolder.length; i++) {
			
				placeHolderWhite += " ";
			}
			
			// Find all the icon tag & where they are located
			var _partialLocs:Array = [];
			
			for(var j:int = 0; j<icons.length; j++) {
				// Replace the icon tag with placeholder tag
				tempObject = icons[j];
				myString = myString.replace(new RegExp(tempObject.tag, "gmi"), placeHolder);
				var index:int = 0;
				while (true) {
				//for (var k:int=0; k<icons.length; k++) {
					// Find every placeholder tag and mark their location
					index = myString.indexOf(placeHolder, index);
					if (index > 0)
					{
						_partialLocs.push( { index: index, iconTag: tempObject } );
						_iconLocs.push( { index: index, iconTag: tempObject } );
						index += placeHolder.length+1;
					}
					else
					{
						break;
					}
				}
				
				// Replace all the placeholder tag with whitespaces
				myString = myString.replace(new RegExp(placeHolder, "gmi"), placeHolderWhite);
			}
			
			txtField.text = myString;
			// For every marked location, add the proper smiley face
			for each(var obj:Object in _partialLocs) {
				// Call the Icon constructor
				ico= DisplayObject(new DuplicateDisplayObject().duplicateImageAsSprite(obj.iconTag.mc));
				
				// Get the location where we should insert our icon
				var rect:Rectangle = txtField.getCharBoundaries(obj.index);
				
				// Resize the icon based on font height, but maintain aspect ratio
				var aspect:Number = ico.width / ico.height;
				ico.width = rect.height;
				ico.height = ico.width * aspect;
				
				// Center the icon within the available space
				ico.x = rect.x + ((rect.width * placeHolderWhite.length) / 2) - (ico.width / 2);
				ico.y = rect.y;
				
				sprite.addChild(ico);
			}		
		}
		
		public function updateTextField():void {
			// Remove all existing Smiley Face
			reset();
			
			placeHolderWhite = new String();
			
			for (var i:int = 0; i < placeHolder.length; i++) {
			
				placeHolderWhite += " ";
			}
			
			// Find all the icon tag & where they are located
			_partialLocs = [];
			
			for(var j:int = 0; j<icons.length; j++) {
				// Replace the icon tag with placeholder tag
				tempObject = icons[j];
				txtField.text = txtField.text.replace(new RegExp(tempObject.tag, "gmi"), placeHolder);
				var index:int = 0;
				while (true) {
				//for (var k:int=0; k<icons.length; k++) {
					// Find every placeholder tag and mark their location
					index = txtField.text.indexOf(placeHolder, index);
					if (index > 0)
					{
						_partialLocs.push( { index: index, iconTag: tempObject } );
						_iconLocs.push( { index: index, iconTag: tempObject } );
						index += placeHolder.length+1;
					}
					else
					{
						break;
					}
				}
				
				// Replace all the placeholder tag with whitespaces
				txtField.text = txtField.text.replace(new RegExp(placeHolder, "gmi"), placeHolderWhite);
			}
			// For every marked location, add the proper smiley face
			for each(var obj:Object in _partialLocs) {
				// Call the Icon constructor
				ico= DisplayObject(new DuplicateDisplayObject().duplicateImageAsSprite(obj.iconTag.mc));
				
				// Get the location where we should insert our icon
				var rect:Rectangle = txtField.getCharBoundaries(obj.index);
				
				// Resize the icon based on font height, but maintain aspect ratio
				var aspect:Number = ico.width / ico.height;
				ico.width = rect.height;
				ico.height = ico.width * aspect;
				
				// Center the icon within the available space
				ico.x = rect.x + ((rect.width * placeHolderWhite.length) / 2) - (ico.width / 2);
				ico.y = rect.y;
				
				sprite.addChild(ico);
			}
		}
		
		public function retriveFormatedLine(unformattedString:String):String {
			
			var tempString:String=unformattedString;
			// Remove all existing Smiley Face
			//forceCleanObjects();
			
			placeHolderWhite = new String();
			
			for (var i:int = 0; i < placeHolder.length; i++) {
				
				placeHolderWhite += " ";
			}
			
			// Find all the icon tag & where they are located
			_partialLocs = [];
			
			for(var j:int = 0; j<icons.length; j++) {
				// Replace the icon tag with placeholder tag
				tempObject = icons[j];
				tempString = tempString.replace(new RegExp(tempObject.tag, "gmi"), placeHolder);
				var index:int = 0;
				while (true) {
					//for (var k:int=0; k<icons.length; k++) {
					// Find every placeholder tag and mark their location
					index = tempString.indexOf(placeHolder, index);
					if (index >= 0){
						_partialLocs.push( { index: index+txtField.text.length, iconTag: tempObject } );
						_iconLocs.push( { index: index+txtField.text.length, iconTag: tempObject } );
						index += placeHolder.length+1;
					}else{
						break;
					}
				}
				
				// Replace all the placeholder tag with whitespaces
				tempString = tempString.replace(new RegExp(placeHolder, "gmi"), placeHolderWhite);
			}
			return tempString;
		}
		
		public function updateEmoticons(cleanOptValue:Boolean=false):void{
			var tempLocs:Array = new Array;
			tempLocs = _partialLocs;
			if(cleanOptValue){
				forceCleanObjects();
				_partialLocs=_iconLocs;
			}
			// For every marked location, add the proper smiley face
			for each(var obj:Object in _partialLocs) {
				// Call the Icon constructor
				ico= DisplayObject(new DuplicateDisplayObject().duplicateImageAsSprite(obj.iconTag.mc));
				
				// Get the location where we should insert our icon
				var rect:Rectangle = txtField.getCharBoundaries(obj.index);
				
				// Resize the icon based on font height, but maintain aspect ratio
				var aspect:Number = ico.width / ico.height;
				ico.width = rect.height;
				ico.height = ico.width * aspect;
				
				// Center the icon within the available space
				ico.x = rect.x + ((rect.width * placeHolderWhite.length) / 2) - (ico.width / 2);
				ico.y = rect.y;
				ico.cacheAsBitmap=true;
				sprite.addChild(ico);
			}
			_partialLocs = tempLocs;
		}
		
		public function updateEmoticonsOnLineAdjust():void {
			var lineHeight:Number=txtField.getCharBoundaries(0).height+txtField.defaultTextFormat.leading;
			for (var i:int=0;i<sprite.numChildren; i++){
				sprite.getChildAt(i).y-=lineHeight;
			}
		}
		
		public function get byLine():Boolean
		{
			return _byLine;
		}

		public function set byLine(value:Boolean):void
		{
			_byLine = value;
		}

	}
}